package org.streets.eis.ext.analysis.internal.buildlogic;

import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.streets.commons.util.StringUtils;
import org.streets.database.SQLConnection;
import org.streets.database.datadict.DataDict;
import org.streets.database.datadict.Relation;
import org.streets.database.datadict.TableDefinition;
import org.streets.database.datadict.TableRelations;
import org.streets.eis.ext.analysis.entities.QueryStruct;

public class SqlBuilderArithmetic {

	private static final long serialVersionUID = 1L;
	protected DataDict _dict;
	private TableRelations _relations;
	private Logger _logger;
	protected final SQLConnection _connection;
	
	public SqlBuilderArithmetic(Logger logger, DataDict dict, TableRelations relations,SQLConnection connection) {
		this._dict = dict;
		this._relations = relations;
		this._logger = logger;
		this._connection = connection;
	}
	   
	public String buildFromClause(QueryStruct struct) {
		if (struct.getTables().size() == 1){			
			String tableName = struct.getTables().get(0).getTableDef().getName();
			String alias = struct.getTables().get(0).getAlias();
			if (StringUtils.isEmpty(alias)) {
				return tableName;
			}else{
				return tableName + " as " + alias;
			}
		}
		
		//1.TODO:优化：首先判断一下选择的表之间是否有直接关系，有则直接构造，否则则进行如下的构造
		
		//1.取所在的组
		int[] group = getIncludedGroup(struct.getTableNames());		
		//2.优化:
		//Optimize(group);
		//3.build join clause
		String clause = buildFromClause(group);		
	 
		return clause;
	 
	}
	
	private int[] getIncludedGroup(String[] selectedTables) {
		List<Queue> allgroup = getEntityGroups();
		List<String> entities = findTables();				
		int[] indexs = matrixIndexs(selectedTables,entities.toArray(new String[0]));
		
		for(Queue q :allgroup){
			int[] group = new int[q.getLength()];
			int i = 0;
			while (! q.isEmpty()) {
				group[i] = ((Integer)q.deQueue()).intValue();
				i++;
			}
			
			if (isAllInGroup(indexs,group)){
				return group;
			}
		}
			
		return null;
	}
	
	private boolean isAllInGroup(int[] indexs,int[] group){
		int count = 0;
		for (int i=0 ; i<indexs.length ; i++){
			for (int j=0 ; j<group.length ; j++){
				if (indexs[i]==group[j]){
					count++;
				}
			}
		}
		
		if (count == indexs.length){
			return true;
		}
		
		return false;
		
	}
	private List<String> findTables() {
		List<String> names = new ArrayList<String>(_dict.getTableDefs().size());
		for (TableDefinition def : _dict.getTableDefs()) {
			names.add(def.getName());
		}
		return names;
	}
	
private int[] matrixIndexs(String[] selectedEntities, String[] allEntities) {
		
		int[] ind =new int[selectedEntities.length];
		
		for(int k=0 ;k < selectedEntities.length;k++){
			String selected = selectedEntities[k];
			for(int i=0; i < allEntities.length ;i++){
				String tmp =  allEntities[i];
				if(tmp.equalsIgnoreCase(selected)){
				  ind[k] = i;	
				}
			}
		}
		
		return ind;
		
	}

	private List<Queue> getEntityGroups(){
		//从全局缓存中取得？否则次次得计算
		List<Queue> qs = groupEntity();
		return qs;
	}

	public List<Queue> groupEntity() {
		List<String> entities = findTables();
		//cleanCodeTable(entities);//去掉代码表 
		
		List<Relation> ers = _relations.getRelations();
		List<Queue> list = groupEntity(entities, ers);//分组结果
		
		return list;
	}
	private List<Queue> groupEntity(List<String> entities, List<Relation> ers) {
		List<Queue> qs = new ArrayList<Queue>();
		int[][] adjMatrix = Matrix.createMatrix(entities,ers);//create邻接矩阵
		
		Graph.hasVisit = new boolean[entities.size()];
		for(int begin = 0; begin < entities.size(); begin++)//所有顶点
		{
			
			//先找出几个根结点来，从根节点开始进行遍历
			if ((! Graph.hasVisit[begin])&&(isRoot(entities.get(begin),ers)))
			{
				Graph.Q_DFS.clean();
				Graph.traverse_DFS(adjMatrix, begin);
				Queue q = Graph.Q_DFS.clone();//结果:一个联通图
				qs.add(q);
			}
		}

		return qs;
	}

	
	private boolean isRoot(String table, List<Relation> ers){		
		for(Relation er:ers){
			//不作为其他表的子表的表，则为根表
			if (er.getTargetTable().equalsIgnoreCase(table)){
				return false;
			}
		}
	
		return true;	
	}
	
	
	private String buildFromClause(int[] group){
		//group里面放的是Entity在List<Entity>中的索引 //【转换为关系树】
		List<Relation> ers = new ArrayList<Relation>();
		List<String> preEntities = new ArrayList<String>();
		List<String> allEntities = convertEntity(group);
		
		//查找并构造group里的Entity之间的关系列表
		preEntities.add(allEntities.get(0));//初始化第一个
		for(int i=1; i < allEntities.size();i++){
			Relation er = findER(allEntities.get(i),preEntities);//肯定有关系，没关系不会出现;【关系需要转换】对对照表的判断分析??
			ers.add(er);
			preEntities.add(allEntities.get(i));
		}
		
		return buildFromClause(ers);
	}	
	
	private String buildFromClause(List<Relation> ers){
		if (ers.size() > 0)  {
		Relation er0 = ers.get(0);
		String s = "";
		for(int i= 1 ; i<ers.size() ; i++){
			s = s + " join " + ers.get(i).getTargetTable() 
 			      + " on "+ ers.get(i).getHostTable()+"."+ers.get(i).getHostColumn() 
 			      + " = " + ers.get(i).getTargetTable()+"." +ers.get(i).getTargetColumn();
		}
		
		s = " from "  + er0.getHostTable() 
		  + " join "  + er0.getTargetTable() 
		  + " on "    + er0.getHostTable()+"."+er0.getHostColumn()
		  + " = "     + er0.getTargetTable()+"."+er0.getTargetColumn() + s;
		return s;
		}
		else{
			return "";
		}
	}
	
	private List<String> convertEntity(int[] group){
		List<String> list = new ArrayList<String>();
		List<String> entities = findTables();
		//cleanCodeTable(entities);//去掉代码表
		for(int i=0;i<group.length;i++){
			int index = group[i];
			list.add(entities.get(index));
		}
			
		return list;
	}
	
	
	private Relation findER(String tableName,List<String> tableNames){
		for(String t_n : tableNames){
			Relation er = findER(tableName, t_n);//这里应该把ER里面的父子关系转换一下；sql就好写了
			if (er != null){
				return er;
			}
		}
		
		return null;
	}
	
	private Relation findER(String tableName1 ,String tableName2){
		List<Relation> ers = _relations.getRelations();
		//查找关系
		for(Relation r : ers){
			if (((r.getHostTable().equalsIgnoreCase(tableName2))&&(r.getTargetTable().equalsIgnoreCase(tableName1)))
				||
				((r.getHostTable().equalsIgnoreCase(tableName1))&&(r.getTargetTable().equalsIgnoreCase(tableName2)))){				

				return r;
				
			}
		}
			
		return null;
	}

}
